﻿using LruCacheNet;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Web;

namespace HttpFileServer
{
    public class DiskLruCache
    {
        public delegate bool GenerateData(string key,out string data);

        private string name;
        private LruCache<string, string> cache = new LruCache<string, string>(1000);
        private GenerateData _generate;
        private bool ReadText(string path,out string data)
        {
            try
            {
                data =File.ReadAllText(path,Encoding.UTF8);
                return true;
            }
            catch (Exception)
            {
                data = null;
                return false;
            }
        }
        private bool SaveText(string path,string data)
        {
            try
            {
                File.WriteAllText(path, data, Encoding.UTF8);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        private bool AddCache(string key,string data)
        {
            cache.Add(key, data);
            return true;
        }
        private bool ReadDiskCacheOrGenerateAndSave(string key,out string data)
        {
            FileInfo fileInfo = new FileInfo(name+"/"+Util.Sha1(key));
            if (fileInfo.Exists)
            {
                return ReadText(fileInfo.FullName,out data);//从磁盘读取缓存
            }
            else
            {
                return _generate.Invoke(key, out data) && SaveText(fileInfo.FullName, data);
            }
        }
        public DiskLruCache(string name,GenerateData from)
        {
            this.name = name;
            this._generate = from;
            DirectoryInfo directory = new DirectoryInfo(this.name);
            if (!directory.Exists)
            {
                directory.Create();
            }
        }
        public bool Get(string key,out string data)
        {
            //Trace.WriteLine(cache.Count);
            return cache.TryGetValue(key, out data) || (ReadDiskCacheOrGenerateAndSave(key, out data)&&AddCache(key,data));
        }
    }
}
